package net.wicp.tams.common.tracer.instrumentation;

import java.util.List;

import org.apache.commons.collections.CollectionUtils;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.commons.Result;

@Slf4j
public abstract class AbsHandler implements IClassEnhance {
	public final static ClassPool pool = ClassPool.getDefault();

	protected final String className;

	public AbsHandler(String className) {
		this.className = className;
	}

	public abstract Result enhance(CtMethod method, String newMethodName);

	public abstract List<CtMethod> findEnhanceMethods(CtClass cc);

	public abstract Result checkClass(CtClass cc);

	@Override
	public CtClass transformed() {
		pool.importPackage("net.wicp.tams.commons");
		pool.importPackage("net.wicp.tams.commons.tracer");
		pool.importPackage("net.wicp.tams.commons.tracer.agent");
		CtClass cc = null;
		try {
			cc = pool.getCtClass(className);
		} catch (NotFoundException e) {
			log.error("没有找到类[{}]", className);
			return null;
		}

		Result checkResult = checkClass(cc);
		if (!checkResult.isSuc()) {
			log.error("类[{}]检查不通过", className);
			return null;
		}

		List<CtMethod> allmethods = findEnhanceMethods(cc);
		if (CollectionUtils.isEmpty(allmethods)) {
			log.error("类[{}]没有要加强的方法", className);
			return null;
		}
		for (CtMethod ctMethod : allmethods) {
			try {
				CtMethod copiedMethod = CtNewMethod.copy(ctMethod, cc.makeUniqueName(ctMethod.getName()), cc, null);
				copiedMethod.setModifiers(javassist.Modifier.PRIVATE);
				cc.addMethod(copiedMethod);
				Result ret = enhance(ctMethod, copiedMethod.getName());
				if (!ret.isSuc()) {
					log.error("类[{}]的[{}]方法加强不成功", className, ctMethod.getName());
					return null;
				}
			} catch (Exception e) {
				log.error(String.format("类[%s]的[%s]方法加强时异常", className, ctMethod.getName()), e);
				return null;
			}
		}
		log.info("类[{}]已加强[{}]个方法", className, allmethods.size());
		return cc;
	}

}
